//
//  UINavigationComponent.m
//  HybirdPrj
//
//  Created by xiangying on 15/7/3.
//  Copyright (c) 2015年 Elephant. All rights reserved.
//

#import "UINavigationComponent.h"
#import "UIViewCommponent.h"
#import <objc/runtime.h>
#import "KLUtils.h"

static const void *customGestureKey = &customGestureKey;
static const void *delayControllersKey = &delayControllersKey;

@implementation UINavigationController(UINavigationComponent)

+ (void)load {
    // fansj iOS14 popToRootViewController和popToViewController返回tabbar消失了
    replaceInstanceMethods([UINavigationController class], @selector(pushViewController:animated:), @selector(swizzle_pushViewController:animated:));
}

- (NSMutableArray *)gestureIgonre{
    NSMutableArray *array = objc_getAssociatedObject(self, "obj_gestureIgonre");
    if (!array) {
        array = NSMutableArray.array;
        self.gestureIgonre = array;
    }
    return array;
}

- (void)setGestureIgonre:(NSMutableArray *)gestureIgonre{
    objc_setAssociatedObject(self, "obj_gestureIgonre", gestureIgonre, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

+ (NSMutableArray *)gestureIgonre{
    NSMutableArray *array = objc_getAssociatedObject(self, "class_gestureIgonre");
    if (!array) {
        array = NSMutableArray.array;
        self.gestureIgonre = array;
    }
    return array;
}

+ (void)setGestureIgonre:(NSMutableArray *)gestureIgonre{
    objc_setAssociatedObject(self, "class_gestureIgonre", gestureIgonre, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

+ (void)initialize{
//    if ([_sysVersion floatValue] < 9.0) {
//        static dispatch_once_t onceToken;
//        dispatch_once(&onceToken, ^{
//            replaceInstanceMethods([UINavigationController class], @selector(delaysetViewControllers:animated:), @selector(setViewControllers:animated:));
//        });
//    }
}

- (void)addIgnoreGesture:(Class)aClass{
    if (aClass && ![self.gestureIgonre containsObject:aClass]) {
        [self.gestureIgonre addObject:aClass];
    }
}

+ (void)addIgnoreGesture:(Class)aClass{
    if (aClass && ![self.gestureIgonre containsObject:aClass]) {
        [self.gestureIgonre addObject:aClass];
    }
}

- (void)removeIgnoreGesture:(Class)aClass{
    [self.gestureIgonre removeObject:aClass];
}
+ (void)removeIgnoreGesture:(Class)aClass{
    [self.gestureIgonre removeObject:aClass];
}

-(void)push:(UIViewController *)viewController andclose:(UIViewController*)closevc animated:(BOOL)animated completion:(void(^)(void))completion{
    NSMutableArray* array = [self.viewControllers mutableCopy];
    if (closevc) {
        [array removeObject:closevc];
    }
    if (viewController) {
        [array addObject:viewController];
    }
    [self setViewControllers:array animated:animated completion:completion];
}

#pragma mark - popgesture

+ (void)setFullPopGestureEnabled:(BOOL)enabled{
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:enabled] forKey:@"fullPopGestureEnabled"];
}

+ (void)setFullPopGestureDisabled:(BOOL)disabled{
    [[NSUserDefaults standardUserDefaults] setBool:disabled forKey:@"fullPopGestureDisEnabled"];
}

//defalut true
+ (BOOL)fullPopGestureEnabled{
    return ![[NSUserDefaults standardUserDefaults] boolForKey:@"fullPopGestureDisEnabled"];;
}

- (void)viewDidLoad{
    [super viewDidLoad];
    
    // 系统相册delegate被替换了，所以去掉
//    self.delegate = self;
    
    if ([UINavigationController fullPopGestureEnabled]) {
        // 获取系统自带滑动手势的target对象
        if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]){
            // 获取系统自带滑动手势的target对象
            id target = self.interactivePopGestureRecognizer.delegate;
            // 创建全屏滑动手势，调用系统自带滑动手势的target的action方法
            UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:NSSelectorFromString(@"handleNavigationTransition:")];
            // 给导航控制器的view添加全屏滑动手势
            [self.view addGestureRecognizer:pan];
            self.customGesture = pan;
            
            // 禁止使用系统自带的滑动手势
            self.interactivePopGestureRecognizer.enabled  = NO;
            self.interactivePopGestureRecognizer.delegate = nil;
        }
    }
    self.navigationBar.barStyle = UIBarStyleBlack;
    self.navigationBar.translucent = NO;

    [self popGesture:YES];
}

- (void)popGesture:(BOOL)gesture{
    
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])
    {
        UIGestureRecognizer *gestureRecognizer = self.customGesture;
        if (!gestureRecognizer) {
            gestureRecognizer = self.interactivePopGestureRecognizer;
        }
        if (gesture) {
            gestureRecognizer.enabled  = YES;
            gestureRecognizer.delegate = self;
        }else{
            gestureRecognizer.enabled  = NO;
            gestureRecognizer.delegate = nil;
        }
    }
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if (gestureRecognizer == self.currentPopgesture) {
        if (self.viewControllers.count <= 1) {
            return NO;
        }
        // Ignore when the beginning location is beyond max allowed initial distance to left edge.
//        CGPoint beginningLocation = [gestureRecognizer locationInView:gestureRecognizer.view];
//        CGFloat maxAllowedInitialDistance = self.view.frame.size.width/2;
//        if (beginningLocation.x > maxAllowedInitialDistance) {
//                return NO;
//        }
        
        // Ignore pan gesture when the navigation controller is currently in transition.
        if ([[self valueForKey:@"_isTransitioning"] boolValue]) {
            return NO;
        }
        
        // Prevent calling the handler when the gesture begins in an opposite direction.
        CGPoint translation = [self.currentPopgesture translationInView:gestureRecognizer.view];
        if (translation.x <= 0) {
            return NO;
        }
    }
    return YES;
}

#pragma mark - properties

- (UIPanGestureRecognizer*)currentPopgesture{
    if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]){

        UIPanGestureRecognizer *gestureRecognizer = self.customGesture;
        if (!gestureRecognizer) {
            gestureRecognizer = (UIPanGestureRecognizer*)self.interactivePopGestureRecognizer;
        }
        
        return gestureRecognizer;
    }
    
    return nil;
}

- (UIPanGestureRecognizer*)customGesture{
    return objc_getAssociatedObject(self, customGestureKey);
}

- (void)setCustomGesture:(UIPanGestureRecognizer *)customGesture{
    objc_setAssociatedObject(self, customGestureKey, customGesture, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

#pragma mark - orientation

- (BOOL)shouldAutorotate{
    return YES;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations{
    if (self.topViewController) {
        @try {
            return [self.topViewController supportedInterfaceOrientations];
        }
        @catch (NSException *exception) {
            return UIInterfaceOrientationMaskPortrait;
        }
        @finally {
            
        }
    }
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0)
{
    if (self.topViewController) {
        @try {
            return [self.topViewController preferredInterfaceOrientationForPresentation];
        }
        @catch (NSException *exception) {
            return UIInterfaceOrientationPortrait;
        }
        @finally {
            
        }
    }
    return UIInterfaceOrientationPortrait;
}

#pragma mark -
- (void)swizzle_pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.viewControllers.count > 0) {
            // 当前导航栏, 只有第一个viewController push的时候设置隐藏
        if (self.viewControllers.count == 1) {
            viewController.hidesBottomBarWhenPushed = YES;
        }else {
            viewController.hidesBottomBarWhenPushed = NO;
        }
    } else {
        viewController.hidesBottomBarWhenPushed = NO;
    }
    [self swizzle_pushViewController:viewController animated:animated];
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void(^)(void))completion{
    viewController.completionBlock = completion;
    self.delegate = self;
    [self pushViewController:viewController animated:animated];
}

//- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void (^)(void))completion animatorManager:(NBTransitionManager *)animatorManager {
//    if (_isGreatDevice) {
//        viewController.completionBlock = completion;
//        self.delegate = animatorManager;
//        [self pushViewController:viewController animated:animated];
//    }else {
//        self.delegate = self;
//        [self pushViewController:viewController animated:animated completion:completion];
//    }
//}

- (void)setViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated completion:(void(^)(void))completion{
    [viewControllers lastObject].completionBlock = completion;
    [self setViewControllers:viewControllers animated:animated];
}

- (NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated completion:(void(^)(void))completion{
    viewController.completionBlock = completion;
    return [self popToViewController:viewController animated:animated];
}

- (UIViewController *)popViewControllerAnimated:(BOOL)animated completion:(void(^)(void))completion{
    if (self.viewControllers.count >1) {
        [self.viewControllers objectAtIndex:self.viewControllers.count-2].completionBlock = completion;
    }
    return [self popViewControllerAnimated:animated];
}


- (NSMutableArray *)delayControllers{
    return objc_getAssociatedObject(self, delayControllersKey);
}

- (void)setDelayControllers:(NSMutableArray *)delayControllers{
    objc_setAssociatedObject(self, delayControllersKey, delayControllers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)delaysetViewControllers:(NSArray<UIViewController *> *)viewControllers animated:(BOOL)animated{
    if (!self.delayControllers) {
        self.delayControllers = [NSMutableArray arrayWithArray:viewControllers];
    }
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(delaySetViewControllers) object:nil];
    [self performSelector:@selector(delaySetViewControllers) withObject:nil afterDelay:0.3];
}

- (void)delaySetViewControllers{
    [self delaysetViewControllers:self.delayControllers animated:YES];
    self.delayControllers = nil;
}

@end
